/**
 * Copyright 2011 Honeywell Federal Manufacturing & Technologies, LLC. This material was produced under U.S. Government
 * contract DE-ACO4-01AL66850, Honeywell Federal Manufacturing & Technologies, LLC, (FM&T) with the U. S. Department of
 * Energy for the operation of the Kansas City Plant . The U.S. Government has rights to use, reproduce, and distribute
 * this software.  NEITHER THE GOVERNMENT NOR Honeywell Federal Manufacturing & Technologies, LLC, MAKES ANY WARRANTY,
 * EXPRESS OR IMPLIED, OR ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE.  If software is modified to produce
 * derivative works, such modified software should be clearly marked, so as not to confuse it with the version available
 * from FM&T.
 *
 * Additionally, this program is free software; you can redistribute it and/or modify it under the terms of the GNU
 * General Public License Version 3 published by the Free Software Foundation. Accordingly, this program is distributed in
 * the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this library.
 * If not, see http://www.gnu.org/licenses/.
 */
package org.braintrain.tapestry.encoders;

import org.apache.tapestry.Tapestry;
import org.apache.tapestry.engine.ServiceEncoder;
import org.apache.tapestry.engine.ServiceEncoding;
import org.apache.tapestry.services.ServiceConstants;
import org.braintrain.domain.types.NavigationType;
import org.braintrain.tapestry.services.ContentViewService;

import javax.servlet.ServletContext;
import java.util.StringTokenizer;

/**
 * A Tapestry Service Encoder for friendly URLS when dealing with BrainTrain ContentBase
 * pages.
 * 
 * @author John Ericksen
 *
 */

public class ContentServiceEncoder implements ServiceEncoder {
    
    public static final String PAGE_PATH = "pages";
    public static final String DIRECT_PAGE_PATH = "directpages";

    /**
     * Encode the Friendly URL for a Navigation from an external link
     * 
     */
    public void encode(ServiceEncoding encoding) {
        
        String service = encoding.getParameterValue(ServiceConstants.SERVICE);
        
        String page = encoding.getParameterValue(ServiceConstants.PAGE);
        
        String[] params = encoding.getParameterValues(ServiceConstants.PARAMETER);

        if(service.equals(Tapestry.EXTERNAL_SERVICE) && page != null && NavigationType.contains(page) && params != null && params.length > 0){
            //build friendly URL
            encoding.setServletPath("/" + buildPath(PAGE_PATH , page, params));
            
            //clear out variables
            encoding.setParameterValue(ServiceConstants.SERVICE, null);
            encoding.setParameterValues(ServiceConstants.PARAMETER, null);
            encoding.setParameterValue(ServiceConstants.PAGE, null);
        }
        
    }
    /**
     * Decode the encoded friendly URL to an external link with the appropriate parameters
     */
    public void decode(ServiceEncoding encoding) {
        String servletPath = encoding.getServletPath();
        
        //regular page link (points to External Page)
        if(servletPath.equals("/" + PAGE_PATH))
        {
            String contentId = encoding.getPathInfo();
            int slashIndex = contentId.lastIndexOf('/');
            int htmlIndex = contentId.lastIndexOf(".htm");
            
            contentId = contentId.substring(
                            slashIndex == -1? 0 : slashIndex + 1, 
                            htmlIndex == -1? contentId.length() : htmlIndex);
            
            int decimalIndex = contentId.indexOf('.');
            
            if(decimalIndex != -1)
            {
            
                String type = contentId.substring(0, decimalIndex);
                
                String[] params = parseParameters(contentId.substring(decimalIndex));

                //remaining are service parameters
                
                if(NavigationType.contains(type))
                {
                    encoding.setServletPath("/app");
                    encoding.setParameterValues(ServiceConstants.PARAMETER, params);
                    
                    encoding.setParameterValue(ServiceConstants.PAGE, type);
                    
                    encoding.setParameterValue(ServiceConstants.SERVICE, Tapestry.EXTERNAL_SERVICE);
                }
            }
        }
        
        //direct page link () (points to IEngineService)
        else if(servletPath.equals("/" + DIRECT_PAGE_PATH))
        {
            String contentId = encoding.getPathInfo().substring(1);
            
            int htmlIndex = contentId.lastIndexOf(".htm");
            String id = null;
            if(htmlIndex != -1)
            {
                id = contentId.substring(0, htmlIndex);
                
                encoding.setServletPath("/app");
                encoding.setParameterValue(ServiceConstants.SERVICE, ContentViewService.SERVICE_NAME);
                encoding.setParameterValue(ContentViewService.NAVIGATION_ID, id);
            }
        }
    }
    
    /**
     * Build the simple page path
     */
    public static String buildPagePath(NavigationType type, String[] params) {
        return buildPath(PAGE_PATH, type.name(), params);
    }
    
    /**
     * Build the direct page path
     */
    public static String buildDirectPagePath(ServletContext context, String[] params) {
        return context.getContextPath() + "/" + buildPath(DIRECT_PAGE_PATH, null, params);
    }

    private static String buildPath(String type, String page, String[] params){
        StringBuffer buff = new StringBuffer();
        
        buff.append(type)
            .append('/');
        
        if(page != null)
        {
            buff.append(page)
                .append('.');
        }
        
        
        for(String s: params)
        {
            if(!s.equals("X"))
            {
                buff.append(s)
                    .append('.');
            }
        }
        
        buff.append("html");
        
        return buff.toString();
    }
    
    public static String[] parsePagePath(String path)
    {
        return parsePath(path, PAGE_PATH);
    }
    
    public static String[] parseDirectPagePath(String path)
    {
        return parsePath(path, DIRECT_PAGE_PATH);
    }
    
    private static String[] parsePath(String path, String type)
    {
        String[] params = null;
        
        int pagesIndex = path.indexOf(type + "/");
        
        if(pagesIndex != -1)
        {
            String variablePath = path.substring(pagesIndex + type.length() + 1);
            
            // remove .htm*
            int htmlIndex = variablePath.lastIndexOf(".htm");
            
            if(htmlIndex != -1)
            {
                variablePath = variablePath.substring(0, htmlIndex);
            }
            
            params = parseParameters(variablePath);
        }
        
        return params;
    }

    
    private static String[] parseParameters(String path)
    {
        
        StringTokenizer token = new StringTokenizer(path, ".");
        
        String[] params = new String[token.countTokens()];
        
        int i = 0;
        
        while(token.hasMoreTokens())
        {
            params[i++] = token.nextToken();
        }
        
        return params;
        
    }

}
